﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlexFlow
{
    /// <summary>
    /// 为操作结果提供封装
    /// </summary>
    public sealed class OperateResult
    {
        /// <summary>
        /// 获取或设置操作结果的代码
        /// </summary>
        public int ResultCode { get; set; }
        /// <summary>
        /// 获取或设置操作结果的子结果
        /// </summary>
        public OperateResult InnerResult { get; set; }
        /// <summary>
        /// 获取或设置操作结果的消息
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 获取操作结果的详细消息
        /// </summary>
        public string FullMessage
        {
            get
            {
                OperateResult res = this;
                StringBuilder sb = new StringBuilder();
                while (res != null)
                {
                    sb.AppendLine("->" + res.Message);
                    res = res.InnerResult;
                }
                return sb.ToString();
            }
            set
            {
                ;
            }
        }
        /// <summary>
        /// 获取当前操作结果的源头消息
        /// </summary>
        /// <remarks>
        /// 源头消息代表最深的操作结果消息
        /// </remarks>
        public string SourceMessage
        {
            get
            {
                OperateResult res = this;
                while (res.InnerResult != null)
                    res = res.InnerResult;
                return res.Message;
            }
            set
            {
                ;
            }
        }
        /// <summary>
        /// 获取或设置操作结果的附加数据
        /// </summary>
        public object Tag { get; set; }
        /// <summary>
        /// 构造操作成功的结果
        /// </summary>
        /// <param name="tag">
        /// 该结果的附加数据
        /// </param>
        public static OperateResult SuccessResult(object tag = null)
        {
            return new OperateResult()
            {
                ResultCode = 200,
                Message = "操作成功！",
                Tag = tag
            };
        }
        /// <summary>
        /// 构造操作失败的结果
        /// </summary>
        /// <param name="errCode">
        /// 错误码
        /// </param>
        /// <param name="message">
        /// 错误消息
        /// </param>
        /// <param name="tag">
        /// 结果的附加数据
        /// </param>
        /// <param name="innerResult">
        /// 子结果
        /// </param>
        /// <returns></returns>
        public static OperateResult FailResult(int errCode, string errMessage, object tag = null, OperateResult innerResult = null)
        {
            return new OperateResult()
            {
                ResultCode = errCode,
                Message = errMessage,
                Tag = tag,
                InnerResult = innerResult
            };
        }
        /// <summary>
        /// 根据子操作结果决定返回的操作结果
        /// </summary>
        /// <param name="checkResult">
        /// 子操作结果
        /// </param>
        /// <param name="successResult">
        /// 如果子操作成功，则返回该结果
        /// </param>
        /// <param name="failResult">
        /// 如果子操作失败，则返回该结果，并将该结果的InnerResult赋值
        /// </param>
        /// <returns>
        /// 若子操作成功，则返回successResult，否则返回failResult
        /// </returns>
        public static OperateResult CheckResult(OperateResult checkResult, OperateResult successResult, OperateResult failResult)
        {
            if (checkResult.ResultCode == 200)
            {
                return successResult;
            }
            else
            {
                failResult.InnerResult = checkResult;
                failResult.Message += "->" + checkResult.Message;
                return failResult;
            }
        }
        public override bool Equals(object obj)
        {
            if (!(obj is OperateResult))
            {
                return false;
            }
            return this.ResultCode.Equals((obj as OperateResult).ResultCode);
        }

        public override int GetHashCode()
        {
            return this.ResultCode.GetHashCode();
        }
    }
}
